﻿using System.Collections.Concurrent;
using System.Text;
using Ke.Bee.Shared.Abstractions;
using Ke.Bee.Shared.Models;
using Ke.Bee.Shared.Models.Uploads;
using Ke.Bee.Transcription.Abstractions;
using Ke.Bee.Transcription.Hubs;
using Ke.Bee.Transcription.Models;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace Ke.Bee.Transcription.Impl;

/// <summary>
/// 语音识别服务
/// </summary>
public class TranscriptionService : ITranscriptionService
{
    private readonly ConcurrentDictionary<string, TranscriptionTask> _tasks = new();
    private readonly ILogger<TranscriptionService> _logger;
    private readonly IAudioExtractor _audioExtractor;
    private readonly IAudioFormatChecker _audioFormatChecker;
    private readonly UploadOptions _uploadOptions;

    public TranscriptionService(ILogger<TranscriptionService> logger, IOptions<UploadOptions> options, IAudioExtractor audioExtractor, IAudioFormatChecker audioFormatChecker)
    {
        _logger = logger;
        _uploadOptions = options.Value;
        _audioExtractor = audioExtractor;
        _audioFormatChecker = audioFormatChecker;
    }

    public async Task<string> ProcessFileAsync(TranscriptionRequest request,
        IHubContext<TranscriptionHub> hubContext,
        CancellationToken ct = default)
    {
        var task = new TranscriptionTask
        {
            Id = request.TaskId,
            FileName = request.FileName,
            FilePath = request.FilePath,
            CreatedAt = DateTimeOffset.UtcNow
        };

        _tasks[task.Id] = task;

        try
        {
            // 发送进度更新
            await hubContext.SendProgressUpdateAsync(request.ConnectionId, request.TaskId, 10, "上传完成", ct);

            // 开始后台处理
            _ = ProcessTranscriptionAsync(request, hubContext, ct);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "文件转写失败");
            await hubContext.SendProgressUpdateAsync(request.ConnectionId, request.TaskId, 0, "文件转写失败", ct);
        }

        return task.Id;
    }

    private async Task ProcessTranscriptionAsync(TranscriptionRequest request,
        IHubContext<TranscriptionHub> hubContext,
        CancellationToken ct = default)
    {
        var task = _tasks[request.TaskId];

        try
        {
            // 步骤1: 音频提取（如果是视频文件）
            await hubContext.SendProgressUpdateAsync(request.ConnectionId, request.TaskId, 11, "提取音频中", ct);
            var audioPath = Path.Combine(_uploadOptions.TempDirectory, $"{Path.GetFileNameWithoutExtension(request.FilePath)}.wav");
            if (!await AudioExtractAsync(request, audioPath, ct))
            {
                await hubContext.SendProgressUpdateAsync(request.ConnectionId, request.TaskId, 0, "提取音频失败", ct);
                _logger.LogError($"抽取音频失败: {request.TaskId}");
                return;
            }

            // 步骤2: 语音识别
            await hubContext.SendProgressUpdateAsync(request.ConnectionId, request.TaskId, 15, "识别语音", ct);
            var transcription = await RecognizeSpeechAsync(audioPath, request.Language, request.Model);

            await Task.Delay(1000);

            // 步骤4: 生成字幕
            await hubContext.SendProgressUpdateAsync(request.ConnectionId, request.TaskId, 90, "生成字幕", ct);
            var srtContent = GenerateSrt(transcription, request.SliceDuration);

            await Task.Delay(1000);

            // 步骤5: 完成
            task.CompletedAt = DateTime.UtcNow;
            task.Result = new TranscriptionResult
            {
                FileName = Path.GetFileNameWithoutExtension(task.FileName),
                SrtContent = srtContent,
                PlainText = GetPlainText(transcription)
            };

            await hubContext.SendProgressUpdateAsync(request.ConnectionId, request.TaskId, 100, "已完成", ct);
            _logger.LogInformation($"任务完成: {request.TaskId}");
        }
        catch (Exception ex)
        {
            await hubContext.SendProgressUpdateAsync(request.ConnectionId, request.TaskId, 0, "处理失败", ct);
            _logger.LogError(ex, $"任务处理失败: {request.TaskId}");
        }
    }

    /// <summary>
    /// 音频提取
    /// </summary>
    /// <param name="request"></param>
    /// <param name="audioPath"></param>
    /// <param name="ct"></param>
    /// <returns></returns>
    private async Task<bool> AudioExtractAsync(TranscriptionRequest request, string audioPath, CancellationToken ct = default)
    {
        // 如果 FilePath 是合适的音频文件，直接复制到临时目录开始处理
        if (await _audioFormatChecker.IsValidFormatAsync(request.FilePath))
        {
            // 异步复制文件
            await using var sourceStream = new FileStream(request.FilePath, FileMode.Open, FileAccess.Read);
            await using var destinationStream = new FileStream(audioPath, FileMode.Create, FileAccess.Write);
            await sourceStream.CopyToAsync(destinationStream, ct);
            return true;
        }

        // 抽取音频
        return await _audioExtractor.ExtractAudioAsync(request.FilePath, audioPath);
    }

    /*
    // 其他方法保持不变...
    public int GetTaskProgress(string taskId)
    {
        return _tasks.TryGetValue(taskId, out var task) ? task.Progress : -1;
    }

    public TranscriptionResult? GetTranscriptionResult(string taskId)
    {
        return _tasks.TryGetValue(taskId, out var task) && task.Status == "已完成"
            ? task.Result
            : null;
    }

    public List<TranscriptionTaskInfo> GetAllTasks()
    {
        return _tasks.Values.Select(t => new TranscriptionTaskInfo
        {
            Id = t.Id,
            FileName = t.FileName,
            Status = t.Status,
            Progress = t.Progress,
            CreatedAt = t.CreatedAt,
            CompletedAt = t.CompletedAt,
            Error = t.Error
        }).ToList();
    }
    */

    public bool RemoveTask(string taskId)
    {
        if (_tasks.TryRemove(taskId, out var task))
        {
            try
            {
                if (!string.IsNullOrEmpty(task.FilePath) && File.Exists(task.FilePath))
                    File.Delete(task.FilePath);

                if (!string.IsNullOrEmpty(task.AudioPath) && File.Exists(task.AudioPath))
                    File.Delete(task.AudioPath);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "清理任务文件失败");
            }
            return true;
        }
        return false;
    }

    // 音频处理方法保持不变...
    private bool IsVideoFile(string filePath)
    {
        var ext = Path.GetExtension(filePath).ToLower();
        return ext is ".mp4" or ".avi" or ".mov" or ".mkv" or ".wmv" or ".flv";
    }

    private async Task<string> ExtractAudioAsync(string videoPath)
    {
        await Task.Delay(500);
        return videoPath.Replace(Path.GetExtension(videoPath), ".wav");
    }

    private async Task<List<SpeechSegment>> RecognizeSpeechAsync(string audioPath, string language, string model)
    {
        await Task.Delay(2000);
        return new List<SpeechSegment>
        {
            new() { Text = "这是第一段识别文本", Start = TimeSpan.FromSeconds(0), End = TimeSpan.FromSeconds(5) },
            new() { Text = "这是第二段识别内容", Start = TimeSpan.FromSeconds(5), End = TimeSpan.FromSeconds(10) },
            new() { Text = "语音识别处理完成", Start = TimeSpan.FromSeconds(10), End = TimeSpan.FromSeconds(15) }
        };
    }

    private string GenerateSrt(List<SpeechSegment> segments, int sliceDuration)
    {
        var srtBuilder = new StringBuilder();

        for (int i = 0; i < segments.Count; i++)
        {
            var segment = segments[i];
            srtBuilder.AppendLine($"{i + 1}");
            srtBuilder.AppendLine($"{FormatTime(segment.Start)} --> {FormatTime(segment.End)}");
            srtBuilder.AppendLine(segment.Text);
            srtBuilder.AppendLine();
        }

        return srtBuilder.ToString();
    }

    private string FormatTime(TimeSpan time)
    {
        return $"{time.Hours:00}:{time.Minutes:00}:{time.Seconds:00},{time.Milliseconds:000}";
    }

    private string GetPlainText(List<SpeechSegment> segments)
    {
        return string.Join(" ", segments.Select(s => s.Text));
    }
}